package com.darren.euc.util;


import com.darren.euc.entity.LoginValidate;

import net.sf.json.JSONObject;

public class JWTUtil {
	
	private static final String HMACMD5_ALGORITHM = "HmacMD5";
	private static final String HMACSHA256_ALGORITHM = "HmacSHA256";
	private static final String ACCESS_HEADER ;	
	private static final String REFRESH_HEADER ;
	static{
		JSONObject json = new JSONObject();
		json.put("typ", "JWT");
		json.put("alg", HMACSHA256_ALGORITHM);
		ACCESS_HEADER = HMacUtil.base64Encoding(json.toString());
		json.put("alg", HMACMD5_ALGORITHM);
		REFRESH_HEADER = HMacUtil.base64Encoding(json.toString());
	}
	
	private static String getAccessTokenSignature(String sourceString,String secretKey){
		String result = null;
		if(!StringUtil.isEmptyOrWhitespace(sourceString)){
			result = HMacUtil.encryptHmacSHA256(sourceString, secretKey);
		}
		return result;
	}
	
	private static String getRefreshTokenSignature(String sourceString,String secretKey){
		String result = null;
		if(!StringUtil.isEmptyOrWhitespace(sourceString)){
			result = HMacUtil.encryptHmacMD5(sourceString, secretKey);
		}
		return result;
	}
	
	
	
	public static String generateAccessJWT(String json){
		return generateAccessJWT(json,PropertyHelper.getAccessTokenSecureSecret());
	}
	
	
	public static String generateAccessJWT(LoginValidate logInfo){
		if( logInfo != null && !StringUtil.isEmptyOrWhitespace(logInfo.getId().toString())){			
			JSONObject payload = getInitialAccessPayload();
			payload.put("id", logInfo.getId());
			return generateAccessJWT(payload.toString(),PropertyHelper.getAccessTokenSecureSecret());
		}
		return null;
	}
	
	
	private static String generateAccessJWT(String json,String secretKey){
		String result = null;
		if(!StringUtil.isEmptyOrWhitespace(json)){
			json = json.trim();
			String payload = HMacUtil.base64Encoding(json.toString());
			String sourceString = String.format("%s.%s",ACCESS_HEADER, payload);
			String signature = getAccessTokenSignature(sourceString, secretKey);
			if(!StringUtil.isEmptyOrWhitespace(signature)){
				result = sourceString + "." + signature;
			}
		}
		return result;
	}
	
	
	public static String generateRefreshJWT(String json){
		return generateRefreshJWT(json,PropertyHelper.getRefreshTokenSecureSecret());
	}
	
	public static String generateRefreshJWT(LoginValidate logInfo){
		if( logInfo != null && !StringUtil.isEmptyOrWhitespace(logInfo.getId().toString())){			
			JSONObject payload = getInitialRefreshPayload();
			payload.put("id", logInfo.getId());
			return generateRefreshJWT(payload.toString(),PropertyHelper.getRefreshTokenSecureSecret());
		}
		return null;
	}
	
	
	private static String generateRefreshJWT(String json,String secretKey){
		String result = null;
		if(!StringUtil.isEmptyOrWhitespace(json)){
			json = json.trim();
			String payload = HMacUtil.base64Encoding(json.toString());
			String sourceString = String.format("%s.%s",REFRESH_HEADER, payload);
			String signature = getRefreshTokenSignature(sourceString, secretKey);
			if(!StringUtil.isEmptyOrWhitespace(signature)){
				result = sourceString + "." + signature;
			}
		}
		return result;
	}
	
	
	public static String updateAccessJWT(String token){
		return updateAccessJWT(token,PropertyHelper.getAccessTokenSecureSecret());
	}
	
	private static String updateAccessJWT(String token,String secretKey){
		if( token != null && !StringUtil.isEmptyOrWhitespace(token)){			
			JSONObject payload = getAccessPayload(token);
			java.util.Date myDate=new java.util.Date();					   
			payload.put("exp", myDate.getTime() + Long.parseLong(PropertyHelper.getAccessTokenExpire())*1000);
			return generateAccessJWT(payload.toString());
		}
		return null;
	}
	
	
	public static String updateRefreshJWT(String token){
		return updateRefreshJWT(token,PropertyHelper.getAccessTokenSecureSecret());
	}
	
	private static String updateRefreshJWT(String token,String secretKey){
		if( token != null && !StringUtil.isEmptyOrWhitespace(token)){			
			JSONObject payload = getRefreshPayload(token);
			java.util.Date myDate=new java.util.Date();					   
			payload.put("exp", myDate.getTime() + Long.parseLong(PropertyHelper.getRefreshTokenExpire())*1000);
			return generateRefreshJWT(payload.toString());
		}
		return null;
	}
	
	
	public static JSONObject getInitialAccessPayload(){
		JSONObject payload = new JSONObject();
		payload.put("iss", "euc");
		java.util.Date myDate=new java.util.Date();					   
		payload.put("exp", myDate.getTime() + Long.parseLong(PropertyHelper.getAccessTokenExpire())*1000);
		return payload;
	}
	
	public static JSONObject getInitialRefreshPayload(){
		JSONObject payload = new JSONObject();
		payload.put("iss", "euc");
		java.util.Date myDate=new java.util.Date();					   
		payload.put("exp", myDate.getTime() + Long.parseLong(PropertyHelper.getRefreshTokenExpire())*1000);
		return payload;
	}
	
	private static boolean verifyAccessJWT(String token,String secretKey){
		boolean validate = false;
		if(!StringUtil.isEmptyOrWhitespace(token)){
			int signLocation = token.lastIndexOf(".");
			if(signLocation > 0 && signLocation < token.length()){
				String sourceString = token.substring(0, signLocation);
				String signatureOld = token.substring(signLocation+1);
				String signatureNew = getAccessTokenSignature(sourceString, secretKey);
				if(signatureOld.equals(signatureNew)){
					validate = true;
				}
			}
		}
		return validate;
	}
	
	
	public static boolean verifyAccessJWT(String token){
		return verifyAccessJWT(token,PropertyHelper.getAccessTokenSecureSecret());
	}
	
	
	
	
	private static boolean verifyRefreshJWT(String token,String secretKey){
		boolean validate = false;
		if(!StringUtil.isEmptyOrWhitespace(token)){
			int signLocation = token.lastIndexOf(".");
			if(signLocation > 0 && signLocation < token.length()){
				String sourceString = token.substring(0, signLocation);
				String signatureOld = token.substring(signLocation+1);
				String signatureNew = getRefreshTokenSignature(sourceString, secretKey);
				if(signatureOld.equals(signatureNew)){
					validate = true;
				}
			}
		}
		return validate;
	}

	public static boolean verifyRefreshJWT(String token){
		return verifyRefreshJWT(token,PropertyHelper.getRefreshTokenSecureSecret());
	}
	
	private static JSONObject getAccessPayload(String token,String secretKey){
		JSONObject payload = null;
		if(!StringUtil.isEmptyOrWhitespace(token)){
			if(verifyAccessJWT(token,secretKey)){
				int payloadStart = token.indexOf(".");
				int signStart = token.lastIndexOf(".");
				if(payloadStart > 0 && payloadStart < signStart && signStart < token.length()){
					String payloadString = token.substring(payloadStart+1, signStart);
					payloadString = HMacUtil.base64Decoding(payloadString);
					payload = JSONObject.fromObject(payloadString);
				}
			}			
		}
		return payload;
	}	
	
	public static JSONObject getAccessPayload(String token){
		return getAccessPayload(token,PropertyHelper.getAccessTokenSecureSecret());
	}

	private static JSONObject getRefreshPayload(String token,String secretKey){
		JSONObject payload = null;
		if(!StringUtil.isEmptyOrWhitespace(token)){
			if(verifyRefreshJWT(token,secretKey)){
				int payloadStart = token.indexOf(".");
				int signStart = token.lastIndexOf(".");
				if(payloadStart > 0 && payloadStart < signStart && signStart < token.length()){
					String payloadString = token.substring(payloadStart+1, signStart);
					payloadString = HMacUtil.base64Decoding(payloadString);
					payload = JSONObject.fromObject(payloadString);
				}
			}			
		}
		return payload;
	}	
	
	public static JSONObject getRefreshPayload(String token){
		return getRefreshPayload(token,PropertyHelper.getAccessTokenSecureSecret());
	}
	
}
